package com.example.zhang.util;

import java.util.Arrays;

public class ProtocolUtil {
    // 信息头
    public static final byte[] HEADER = {(byte)0xFF, (byte)0xFF};
    // 结束标志
    public static final byte[] END = {(byte)0xFF, (byte)0xF7};

    /**
     * 组包：查询帧
     * @param frameNo 帧号
     * @param deviceAddr 设备地址
     * @return 完整帧
     */
    public static byte[] buildQueryFrame(byte frameNo, byte deviceAddr) {
        byte[] frame = new byte[10];
        frame[0] = HEADER[0];
        frame[1] = HEADER[1];
        frame[2] = 0x0A; // 帧长10
        frame[3] = frameNo;
        frame[4] = deviceAddr;
        frame[5] = 0x01; // 功能号
        // 数据区0字节
        // CRC
        byte[] crc = CRC16Util.getCRC16(Arrays.copyOfRange(frame, 2, 6));
        frame[6] = crc[0];
        frame[7] = crc[1];
        frame[8] = END[0];
        frame[9] = END[1];
        return frame;
    }

    /**
     * 组包：启停压缩机控制帧
     * @param frameNo 帧号
     * @param deviceAddr 设备地址
     * @param action 1-启动 0-停止
     * @return 完整帧
     */
    public static byte[] buildCompressorControlFrame(byte frameNo, byte deviceAddr, byte action) {
        byte[] frame = new byte[11];
        frame[0] = HEADER[0];
        frame[1] = HEADER[1];
        frame[2] = 0x0B; // 帧长11
        frame[3] = frameNo;
        frame[4] = deviceAddr;
        frame[5] = 0x02; // 功能号
        frame[6] = action;
        byte[] crc = CRC16Util.getCRC16(Arrays.copyOfRange(frame, 2, 7));
        frame[7] = crc[0];
        frame[8] = crc[1];
        frame[9] = END[0];
        frame[10] = END[1];
        return frame;
    }

    /**
     * 组包：开锁帧(12Byte)
     * @param frameNo 帧号
     * @param deviceAddr 设备地址
     * @param controlBits 2字节，低位在前，bit0~bit11表示锁
     * @return 完整帧
     */
    public static byte[] buildUnlockFrame(byte frameNo, byte deviceAddr, int controlBits) {
        byte[] frame = new byte[12];
        frame[0] = HEADER[0];
        frame[1] = HEADER[1];
        frame[2] = 0x0C; // 帧长12
        frame[3] = frameNo;
        frame[4] = deviceAddr;
        frame[5] = 0x03; // 功能号
        frame[6] = (byte) (controlBits & 0xFF); // 低字节
        frame[7] = (byte) ((controlBits >> 8) & 0xFF); // 高字节
        byte[] crc = CRC16Util.getCRC16(Arrays.copyOfRange(frame, 2, 8));
        frame[8] = crc[0];
        frame[9] = crc[1];
        frame[10] = END[0];
        frame[11] = END[1];
        return frame;
    }

    /**
     * 组包：设置温度帧(11Byte)
     * @param frameNo 帧号
     * @param deviceAddr 设备地址
     * @param tempByte 协议格式温度字节
     * @return 完整帧
     */
    public static byte[] buildSetTempFrame(byte frameNo, byte deviceAddr, byte tempByte) {
        byte[] frame = new byte[11];
        frame[0] = HEADER[0];
        frame[1] = HEADER[1];
        frame[2] = 0x0B; // 帧长11
        frame[3] = frameNo;
        frame[4] = deviceAddr;
        frame[5] = 0x04; // 功能号
        frame[6] = tempByte;
        byte[] crc = CRC16Util.getCRC16(Arrays.copyOfRange(frame, 2, 7));
        frame[7] = crc[0];
        frame[8] = crc[1];
        frame[9] = END[0];
        frame[10] = END[1];
        return frame;
    }

    /**
     * 组包：设置参数帧(28Byte)
     * @param frameNo 帧号
     * @param deviceAddr 设备地址
     * @param params 18字节参数区
     * @return 完整帧
     */
    public static byte[] buildSetParamsFrame(byte frameNo, byte deviceAddr, byte[] params) {
        byte[] frame = new byte[28];
        frame[0] = HEADER[0];
        frame[1] = HEADER[1];
        frame[2] = 0x1C; // 帧长28
        frame[3] = frameNo;
        frame[4] = deviceAddr;
        frame[5] = 0x05; // 功能号
        System.arraycopy(params, 0, frame, 6, 18);
        byte[] crc = CRC16Util.getCRC16(Arrays.copyOfRange(frame, 2, 24));
        frame[24] = crc[0];
        frame[25] = crc[1];
        frame[26] = END[0];
        frame[27] = END[1];
        return frame;
    }

    /**
     * 组包：设置温度控制偏差帧(11Byte)
     * @param frameNo 帧号
     * @param deviceAddr 设备地址
     * @param deviation 偏差字节
     * @return 完整帧
     */
    public static byte[] buildSetDeviationFrame(byte frameNo, byte deviceAddr, byte deviation) {
        byte[] frame = new byte[11];
        frame[0] = HEADER[0];
        frame[1] = HEADER[1];
        frame[2] = 0x0B; // 帧长11
        frame[3] = frameNo;
        frame[4] = deviceAddr;
        frame[5] = 0x06; // 功能号
        frame[6] = deviation;
        byte[] crc = CRC16Util.getCRC16(Arrays.copyOfRange(frame, 2, 7));
        frame[7] = crc[0];
        frame[8] = crc[1];
        frame[9] = END[0];
        frame[10] = END[1];
        return frame;
    }

    /**
     * 组包：设置设备地址帧(16Byte)
     * @param frameNo 帧号
     * @param deviceAddr 设备地址
     * @param devCode 5字节设备编码
     * @param newAddr 新地址
     * @return 完整帧
     */
    public static byte[] buildSetDeviceAddrFrame(byte frameNo, byte deviceAddr, byte[] devCode, byte newAddr) {
        byte[] frame = new byte[16];
        frame[0] = HEADER[0];
        frame[1] = HEADER[1];
        frame[2] = 0x10; // 帧长16
        frame[3] = frameNo;
        frame[4] = deviceAddr;
        frame[5] = 0x09; // 功能号
        System.arraycopy(devCode, 0, frame, 6, 5);
        frame[11] = newAddr;
        byte[] crc = CRC16Util.getCRC16(Arrays.copyOfRange(frame, 2, 12));
        frame[12] = crc[0];
        frame[13] = crc[1];
        frame[14] = END[0];
        frame[15] = END[1];
        return frame;
    }

    /**
     * 组包：上传状态帧(44Byte)
     * @param frameNo 帧号
     * @param deviceAddr 设备地址
     * @param params 18字节参数区
     * @param status 16字节状态区
     * @return 完整帧
     */
    public static byte[] buildStatusUploadFrame(byte frameNo, byte deviceAddr, byte[] params, byte[] status) {
        byte[] frame = new byte[44];
        frame[0] = HEADER[0];
        frame[1] = HEADER[1];
        frame[2] = 0x2C; // 帧长44
        frame[3] = frameNo;
        frame[4] = deviceAddr;
        frame[5] = 0x10; // 功能号
        System.arraycopy(params, 0, frame, 6, 18);
        System.arraycopy(status, 0, frame, 24, 16);
        byte[] crc = CRC16Util.getCRC16(Arrays.copyOfRange(frame, 2, 40));
        frame[40] = crc[0];
        frame[41] = crc[1];
        frame[42] = END[0];
        frame[43] = END[1];
        return frame;
    }

    /**
     * 组包：ACK帧(14Byte)
     * @param frameNo 帧号
     * @param deviceAddr 设备地址
     * @param funcNo 应答功能号
     * @param cmdFrameNo 命令帧号
     * @param data 4字节数据
     * @return 完整帧
     */
    public static byte[] buildAckFrame(byte frameNo, byte deviceAddr, byte funcNo, byte cmdFrameNo, byte[] data) {
        byte[] frame = new byte[14];
        frame[0] = HEADER[0];
        frame[1] = HEADER[1];
        frame[2] = 0x0E; // 帧长14
        frame[3] = frameNo;
        frame[4] = deviceAddr;
        frame[5] = funcNo;// 功能号
        frame[6] = data[0];
        frame[7] = data[1];
        frame[8] = data[2];
        frame[9] = data[3];
        byte[] crc = CRC16Util.getCRC16(Arrays.copyOfRange(frame, 2, 10));
        frame[10] = crc[0];
        frame[11] = crc[1];
        frame[12] = END[0];
        frame[13] = END[1];
        
        return frame;
    }

    // 其他帧组包方法可按需补充
} 